#include <mono/parser/ini_parser.h>
#include <mono/common/string.h>
#include <mono/common/number_parser.h>
#include <iostream>
#include <fstream>
#include <cstdlib>


namespace  mono {

IniParser::IniParser()
{
    
}

IniParser::IniParser(const IniParser &p)
{
    _propmap = p._propmap;
}

IniParser::~IniParser()
{

}

bool IniParser::loadIniParser(const char* fileName, char delimiter, bool verbose, bool multiline /*=false*/)
{
    std::ifstream input(fileName);
    std::string line;

    if(!input.is_open()) 
    {
        std::cout<<  "IniParser::loadIniParser() Could not open the file:" << fileName <<std::endl;
        return false;
    }
    loadIniParser(input, delimiter, verbose, multiline);
    input.close();
    return true;
}

bool IniParser::loadIniParser(std::istream &ist, char delimiter, bool verbose, bool multiline /*=false*/)
{
    std::string line;

    while(ist) {
        getline(ist, line);                       //read one line at a time
        if  (line.find('#') == 0)
            continue;                               //ignore comments
        std::string::size_type pos =
            line.find(delimiter);                   //find the delimiter
        
        if( pos == line.npos )
            return false;                               //ignore if no delimiter is found
        std::string key = line.substr(0,pos);       // get the key
        key = trim(key);
        std::string value = line.substr(pos+1);     //get the value
        value = trim(value);

		if (multiline)
        	_propmap[key] += value;					// allow properties to be spread across multiple lines
        else
        	_propmap[key] = value;
        
        if( verbose)
            std::cout << "Loading key " << key  << " with value " << _propmap[key] << std::endl ;
    }
    return true;
}



void IniParser::setValue(const std::string& key, const std::string& value) {
    _propmap[key] = value;
    return;
}

std::string IniParser::getValue(const std::string& key, const std::string& def) 
{
    if(_propmap.find(key) == _propmap.end()) { 
        return def;
    }
    return _propmap[key];
}

const char* IniParser::getValue(const std::string& key, const char* def) 
{
    if(_propmap.find(key) == _propmap.end()) { 
        return def;
    }
     
     return ((_propmap[key]).c_str());
}



int64_t IniParser::getValue(const std::string& key, int64_t def)
{
	//int64_t ret = def;
    if(_propmap.find(key) == _propmap.end())  {
    	return def;
    }
    int64_t ret;
    bool bret = NumberParser::atoix((_propmap[key]), ret);
    if(!bret) {
        ret = def;
    }
    return ret;
}

double IniParser::getValue(const std::string& key, double def)
{
	double ret = def;
    if(_propmap.find(key) == _propmap.end())  {
    	return def;
    }

    bool bret = NumberParser::parseFloat((_propmap[key]), ret);
    return bret ? ret : def;
}

void IniParser::getList(std::string &outBuf, const std::string& linePrefix) 
{
    std::unordered_map<std::string, std::string>::iterator iter;

    for (iter = _propmap.begin(); iter != _propmap.end(); iter++) {
        if ((*iter).first.size() > 0) {
            outBuf += linePrefix;
            outBuf += (*iter).first;
            outBuf += '=';
            outBuf += (*iter).second;
            outBuf += '\n';
        }
    }

    return;
}

}
